//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------


#include <windows.h>
#include <nkintr.h>
#include <monahans.h>
#include <Littleton.h>
#include <oal_memory.h>
#include <pcireg.h>
#include <fmd.h>
#include <bsp.h>
#include "loader.h"
#include <bootpart.h>
#include "xllp_pm.h"
#include "xllp_pm_dvfm.h"
#include "monahans_base_regs.h"
#include "xllp_defs.h"
#include "xllp_udc.h"
#include "xllp_lcd_plat.h"

#include <flash_cfg.h>
#include <blcommon.h>

//Included for the SD/MMC boot option
#include "SDMMC.h"
#include "FAT.h"

#include "BLMenu.h"
///Basic Menu System
void InitMenuItem( MENU_ITEM *item, WCHAR k, LPCWSTR t, DWORD (*act)(struct MENU_ITEM *), VOID* p1, VOID *p2, VOID*p3,VOID*p4)
{
    (item)->key=(k);
    (item)->text=(t);
    (item)->pfnAction=(act);
    (item)->pParam1=(p1);
    (item)->pParam2=(p2);
    (item)->pParam3=(p3);
    (item)->pParam4=(p4);

}
//------------------------------------------------------------------------------

WCHAR OALBLMenuReadKey(BOOL wait)
{
    CHAR key;

    while ((key = OEMReadDebugByte()) == OEM_DEBUG_READ_NODATA && wait);
    if (key == OEM_DEBUG_READ_NODATA) key = 0;
    return (WCHAR)key;
}


//------------------------------------------------------------------------------

/// Read the input of user.
///
/// @param  szBuffer               [OUT] buffer for input
/// @param  CharCount              [IN] allowed length of text
/// @return     count              Number of characters.
///
UINT32 OALBLMenuReadLine(LPWSTR szBuffer, size_t CharCount)
{
    UINT32 count;
    WCHAR key;

    count = 0;
    while (count < CharCount) {
        key = OALBLMenuReadKey(TRUE);
        if (key == L'\r' || key == L'\n') {
            OALLog(L"\r\n");
            break;
        }
        if (key == L'\b' && count > 0) {
            OALLog(L"\b \b");
            count--;
        }
        else if (key >= L' ' && key < 128 && count < (CharCount - 1)) {
            szBuffer[count++] = key;
            OALLog(L"%c", key);
        }
    }
    szBuffer[count] = '\0';
    return count;

}




/// Print the menu header.
///
/// @param  header               [IN] the format and text of the menu header
///
VOID OALBLMenuHeader(LPCWSTR format, ...)
{
    va_list pArgList;
    UINT32 i;

    va_start(pArgList, format);

    OALLog(L"\r\n");
    for (i = 0; i < 80; i++) OALLog(L"-");
    OALLog(L"\r\n ");
    OALLogV(format, pArgList);
    OALLog(L"\r\n");
    for (i = 0; i < 80; i++) OALLog(L"-");
    OALLog(L"\r\n");
}

//------------------------------------------------------------------------------

/// show the menu and allow settings.
///
/// @param  pMenu               [IN] Menu item
/// @return     0
///
DWORD OALBLMenuShow(MENU_ITEM * pMenu)
{
    LPCWSTR title = pMenu->pParam1;
    MENU_ITEM *aMenu = pMenu->pParam2, *pItem;
    WCHAR key;
    WCHAR key2;

    while (TRUE) {

        OALBLMenuHeader(pMenu->text, title);

        // Print menu items
        for (pItem = aMenu; pItem->key != 0; pItem++) 
        {
            OALLog(L" [%c] ", pItem->key); 
            OALLog(pItem->text,pItem->pParam1,pItem->pParam2,pItem->pParam3,pItem->pParam4);
            OALLog(L"\r\n"); 
        }
        OALLog(L"\r\n Selection: ");

        while (TRUE) {
            // Get key
            key = OALBLMenuReadKey(TRUE);
            // Look for key in menu
            for (pItem = aMenu; pItem->key != 0; pItem++) 
            {
                if(key>=L'a' && key<=L'z')
                {
                    key+= L'A'-L'a';
                }
                key2=pItem->key;

                if(key2>=L'a' && key2<=L'z')
                {
                    key2+= L'A'-L'a';
                }
                if (key2 == key) break;
            }
            // If we find it, break loop
            if (pItem->key != 0) break;
        }

        // Print out selection character
        OALLog(L"%c\r\n", key);

        // When action is NULL return back to parent menu
        if (pItem->pfnAction == NULL) break;
        
        // Else call menu action
        if( pItem->pfnAction(pItem) != 0)
            break;;

    }
    return 0;

}

//------------------------------------------------------------------------------

/// toggle the flag of the menu item according to mask.
///
/// @param  pMenu               [IN/OUT] Menu item
/// @return     0
///
DWORD OALBLMenuEnableMASK32(MENU_ITEM * pMenu)
{
    LPCWSTR title = pMenu->pParam1;
    UINT32 *pFlags = pMenu->pParam2;
    UINT32 mask = (UINT32)pMenu->pParam3;


    // First check input parameter   
    if (title == NULL || pFlags == NULL) {
        OALMSG(OAL_ERROR, (L"ERROR: OALBLMenuEnable: Invalid parameter\r\n"));
        return 0;
    }
    if (mask == 0) mask = 0xFFFF;

    *pFlags ^= mask;

    if(*pFlags&mask)
    {
        pMenu->pParam1=L"Enable";
    }
    else
    {
        pMenu->pParam1=L"Disable";
    }
    return 0;
}

//------------------------------------------------------------------------------

/// toggle the TRUE/FALSE of the menu item.
///
/// @param  pMenu               [IN/OUT] Menu item
/// @return     0
///
DWORD OALBLMenuEnableBOOL(MENU_ITEM * pMenu)
{
    LPCWSTR title = pMenu->pParam1;
    UINT32 *pFlags = pMenu->pParam2;

    // First check input parameter   
    if (pFlags == NULL) {
        OALMSG(OAL_ERROR, (L"ERROR: OALBLMenuEnable: Invalid parameter\r\n"));
        return 0;
    }

    *pFlags = !*pFlags;

    if(*pFlags )
    {
        pMenu->pParam1=L"Enable";
    }
    else
    {
        pMenu->pParam1=L"Disable";
    }
    return 0;
}

DWORD OALBLMenuDWORDChoose(MENU_ITEM *pMenu)
{
    if(pMenu->pParam1 == NULL)
    {
        OALMSG(OAL_ERROR, (L"ERROR: OALBLMenuDWORDChoose: Invalid parameter\r\n"));
    }
    *(DWORD*)pMenu->pParam1 =(DWORD)pMenu->pParam2;
    return 1;
}

/// Look up the text according to the key
///
/// @param  pMenu               [IN]MENU_ITEM structure
/// @param  key                 [IN]the Menu key
/// @return text       The according text of that key
///         L""        Not found
///
LPCWSTR GetMenuTextP2EQKey(MENU_ITEM * pMenu, DWORD key)
{

    MENU_ITEM *pItem=pMenu;

    while(pItem->key)
    {
        if((DWORD)pItem->pParam2 == key)
            return pItem->text;
        pItem++;
    }
    return L"";
}


/// Provide User a chance to confirm his choice.
///
/// @return TRUE       User confirmed with "Y"
///         FALSE      User canceled with "N"
///
BOOL AreYouSure()
{
    UINT32 Selection;
    EdbgOutputDebugString("\r\nAre you sure? Y or N\r\n");
    while(Selection = OEMReadDebugByte())
    {
        if(Selection == 'Y' || Selection == 'y')
        {
            OEMWriteDebugByte((BYTE)Selection);
            return TRUE;
        }
        if(Selection == 'N' || Selection == 'n')
        {
            OEMWriteDebugByte((BYTE)Selection);
            return FALSE;
        }
    }
    return FALSE;
}


